/*
 * TiffCompressionJpeg
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 */
using System;
using System.IO;
using System.Collections.Generic;
//using System.Drawing;
//using System.Drawing.Imaging;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Petra.Gis.Geometry.Image.Tiff
{
  /// <summary>
  /// A jpeg decoder for files compressed with the <em>jpeg</em> method.
  /// decoder can decompress CompressionType.JPEG and CompressionType.OJPEG
  /// This decoder makes use of the package System.Windows.Media.Imaging, class JpegBitmapDecoder
  /// jpeg data inside tiff block is treated same way as normal JPEG file
  /// threfore normal jpeg decoder and encoder can be used
  /// </summary>
  public unsafe class TiffCompressionJpeg : TiffCompression
  {

    JpegBitmapDecoder _jpegdecoder;  //windows jpeg decoder


    public TiffCompressionJpeg()
      : base() { }


    public TiffCompressionJpeg(BlockBitmapFrame currImage)
      : base(currImage){}



    //public static override TiffCompression CreateCompressionInstance(BlockBitmapFrame currImage)
    //{
    //  return new TiffCompressionJpeg(currImage);

    //}




    public override byte[] DecompressBlock(BitmapBlock block, byte[] comprData, int srcBitsPerSample)
    {

      if (_image == null)
        throw new InvalidOperationException("no image presents to decompress");

      if (srcBitsPerSample == 8)
        _blockPixelFormat = PixelFormats.Gray8;
      else if (srcBitsPerSample == 24)
        _blockPixelFormat = PixelFormats.Rgb24;
      else
        throw new UnsupportedTypeException("jpeg currently supports only planar gray or truecolor 24 rgb");

      _jpegdecoder = new JpegBitmapDecoder(new MemoryStream(comprData), BitmapCreateOptions.None, BitmapCacheOption.Default);

      //_decoder.Frames[0];
      BitmapSource jpegBitmapSource = _jpegdecoder.Frames[0];

      int outStride = BitmapBlock.GetStrideLenght(block.Bounds.Width, _blockPixelFormat.BitsPerPixel);
      byte[] pixelArray = new byte[outStride * block.Bounds.Height];

      jpegBitmapSource.CopyPixels(pixelArray, outStride, 0);

      return pixelArray;
    }





    ///// <summary>
    ///// decode whole image as new bitmap into its original colorspace and samplePerPixel depth
    ///// </summary>
    //public void decompress()
    //{

    //  //todo: change this all by image type !!!
    //  _blockPixelFormat = PixelFormat.Format8bppIndexed;
    //  _outPixelFormat = _blockPixelFormat;
    //  _bitsPerPixel = 8;
    //  //end

    //  int bandDataBytesLength;

    //  //create new bitmap
    //  Bitmap bmp = new Bitmap(_image.PixelWidth, _image.PixelHeight, _outPixelFormat); //just for now

    //  foreach (KeyValuePair<BandType, Band> bdnKey in _image.Bands)
    //  {
    //    //compute skip bytes for current band, if interleaved
    //    int skipOtherBandBytesLenght = _bitsPerPixel - bdnKey.Value.BitsPerBand;
    //    if ((skipOtherBandBytesLenght % 8) != 0 || (bdnKey.Value.BitsPerBand % 8) != 0)
    //      throw new ArgumentException("unsupported bit depth in image or in band, both must be modulo of 8");

    //    bandDataBytesLength = bdnKey.Value.BitsPerBand >> 3; // = / 8

    //    foreach (Block b in bdnKey.Value.Blocks)
    //    {
    //      //read compressed data from tiff file
    //      _tiffReader.BaseStream.Seek(b.Offset, System.IO.SeekOrigin.Begin);

    //      _jpegdecoder = new JpegBitmapDecoder(new MemoryStream(_tiffReader.ReadBytes(b.CompressedSize)), BitmapCreateOptions.None, BitmapCacheOption.Default);

    //      //_decoder.Frames[0];
    //      BitmapSource bitmapSource = _jpegdecoder.Frames[0];


    //      //handle different block dimensions in tiled images
    //      //LockBits by tile size
    //      BitmapData bd = bmp.LockBits(new Rectangle(b.BlockX1, b.BlockY1, b.Width, b.Height), ImageLockMode.ReadWrite, _outPixelFormat);

    //      //get bitmap start pointer
    //      byte* browPtr = (byte*)bd.Scan0;

    //      //for interleaved images
    //      //start to fill image with data from current band first position
    //      browPtr += (int)bdnKey.Key;

    //      //copy decompressed image back to bitmap

    //      //unlock
    //      bmp.UnlockBits(bd);

    //    }
    //  }

    //  bmp.Save("e:\\rastry\\test1.bmp", ImageFormat.Bmp);


    //}


 
    public override CompressionType[] CompressionTypes
    {
      get { return new CompressionType[] { CompressionType.JPEG, CompressionType.OJPEG }; }
    }
  }
}